package checkers3d.presentation;

import java.awt.Point;
import java.awt.Color;
import java.util.LinkedList;

/**
 * Controls a group of GUIButtonRadio objects. Contains a label for the group
 * and dynamically positions buttons and that are added to it. Buttons are
 * updated using typically radio button logic.
 *
 * @author Ruben Acuna
 */
public class GUIButtonRadioGroup extends GUILabel implements IInputObserver
{
    /**
     * The vertical pad between buttons in pixels.
     */
    private final int BUTTON_PAD = 4;

    /**
     * The vertical pad between the top of the group label and the first button.
     */
    private int labelPad;

    /**
     * The GUIContainer this componenet exits in and the one to which buttons
     * and labels are added.
     */
    private GUIContainer parent;

    /**
     * A list of all the buttons assoicated with this group.
     */
    private LinkedList<GUIButtonRadio> buttons = new LinkedList<GUIButtonRadio>();

    /**
     * A list of all the text labels assoicated with this group's buttons, these
     * are automatically generated.
     */
    private LinkedList<GUILabel> labels = new LinkedList<GUILabel>();

    /**
     * Class constructor that takes a label for the group buttons, the group's
     * position, and the parent GUIContainer.
     *
     * @param text The text label for this group.
     * @param position The position of this group.
     * @param parent The GUIContainer this group exists in.
     */
    public GUIButtonRadioGroup(String text, Point position, GUIContainer parent)
    {
        super(text, Color.WHITE, position);

        this.parent = parent;
        
        labelPad = getRenderResource().getHeight() + BUTTON_PAD;
    }

    /**
     * Adds a GUIButtonRadio object to this group. The button's position is
     * automatically calculated and a text label is generated. Do not use this
     * function outside of the parent GUIContainer's constructor.
     *
     * @param button The GUIButtonRadio object that is being added.
     */
    public void add(GUIButtonRadio button)
    {
        buttons.add(button);

        computePositions();
        computeLabels();

        parent.add(button);
    }

    /**
     * Updates the positions of the group's buttons to be aligned vertically
     * beneath the text label.
     */
    private void computePositions()
    {
        int x = getDrawPosition().x;
        int y = getDrawPosition().y + labelPad;

        for(GUIButtonRadio button : buttons)
        {
            button.setDrawPosition(new Point (x,y));

            y = y + button.getRenderResource().getHeight() + BUTTON_PAD;
        }
    }

    /**
     * Updates the labels next each button.
     */
    private void computeLabels()
    {
        //remove all old labels
        for(GUILabel oldLabel : labels)
            parent.getComponentsList().remove(oldLabel);

        //clear labels list
        labels = new LinkedList<GUILabel>();

        //loop over each button and create a label.
        for(GUIButtonRadio button : buttons)
        {
            GUILabel label = new GUILabel(button.text, Color.WHITE, null);

            //center the label to the right of the radio button image.
            int x = button.getDrawPosition().x + BUTTON_PAD + button.getRenderResource().getWidth();
            int y = button.getDrawPosition().y + ((button.getRenderResource().getHeight() - label.getRenderResource().getHeight()) / 2);
            
            label.setDrawPosition(new Point(x, y));

            labels.add(label);
            parent.add(label);
        }
    }

    /**
     * Handles a click within a visible area by checking it is landed on a
     * GUIButtonRadio and updating accordingly.
     *
     * @param  position  Point object containing coordinates relative to the
     *                   position of the click within the GUIButtonRadioGroup.
    * @see IInputObserver
     */
    public void onClick(Point position)
    {
        GUIButtonRadio buttonClicked = null;

        Point target = new Point(position.x, position.y - labelPad);

        //check to see if one of our buttons was clicked.
        for(GUIButtonRadio button : buttons)
        {
            if(button.getRenderResource().containsPoint(target))
            {
                buttonClicked = button;
                break;
            }
            
            //substract the height of the last button checked so that the point will
            //be aligned relative to the next button.
            target.translate(0, -(button.getRenderResource().getHeight() + BUTTON_PAD));
        }
        
        //if one of our buttons was clicked, turn all buttons off and set that
        //one on.
        if(buttonClicked != null)
        {
            for(GUIButtonRadio button : buttons)
                button.setOff();
            
            buttonClicked.setOn();
        }
    }

    /**
    * Handles a key press by doing nothing.
    *
    * @param  key       The character of the key that was pressed.
    * @see IInputObserver
    */
    public void onKeyPress(char key)
    {
        //do nothing.
    }
}